package drp.snowbell.annotation;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import drp.snowbell.cfg.ModuleConfig;
import drp.snowbell.entity.IEntity;
import drp.snowbell.entity.IPart;
import drp.snowbell.exception.CatchException;
import drp.snowbell.module.IModule;


/**
 * 实体和部件class管理类
 * 
 * @author wuhj
 * 
 */
public class AsmManager {

	/**
	 * 根据模块分类的实体class缓存
	 */
	private Collection<Class<? extends IEntity>> entityClassList;
	/**
	 * 根据模块分类的部件class缓存
	 */
	private Collection<Class<? extends IPart>> partClassList;

	private Class<? extends IModule> moduleClass;

	private AnnotationClassLoader classLoader;// 每个模块一个classLoader,模块直接通信必须通过接口服务

	private ModuleConfig moduleConfig;

	private Map<String, Class<?>> classMap;

	public AsmManager(ModuleConfig moduleConfig) {
		entityClassList = new ArrayList<Class<? extends IEntity>>();
		partClassList = new ArrayList<Class<? extends IPart>>();
		classMap = new HashMap<String, Class<?>>();
		this.moduleConfig = moduleConfig;

		reload(moduleConfig);
	}

	public Class<?> loadClass(String className) throws ClassNotFoundException {
		Class<?> ret = classMap.get(className);
		if (ret == null) {
			ret = classLoader.loadClass(className);
			synchronized (classMap) {
				classMap.put(className, ret);
			}
		}
		return ret;
	}

	/**
	 * 获取模块类
	 * 
	 * @return
	 * @throws ClassNotFoundException
	 */
	@SuppressWarnings("unchecked")
	public Class<? extends IModule> getModuleClass() {
		if (moduleClass == null) {
			String moduleClassName = moduleConfig.getModuleClass();
			if (moduleClassName != null) {
				try {
					moduleClass = (Class<? extends IModule>) loadClass(moduleClassName);
				} catch (ClassNotFoundException e) {
					CatchException.take(e);
				}
			}
		}
		return moduleClass;
	}

	/**
	 * 重新加载
	 * 
	 * @param moduleName
	 *            模块名称
	 */
	public synchronized void reload(ModuleConfig newModuleConfig) {
		moduleClass = null;
		entityClassList.clear();
		partClassList.clear();
		classMap.clear();
		this.moduleConfig = newModuleConfig;

		classLoader = createLoader(getUrls(moduleConfig));

		classLoader.loadAll(entityClassList, partClassList);
	}

	/**
	 * 获取模块实体class列表
	 * 
	 * 
	 * @return
	 */
	public Collection<Class<? extends IEntity>> getEntityClassList() {
		return entityClassList;
	}

	/**
	 * 获取模块部件class列表
	 * 
	 * @return
	 */
	public Collection<Class<? extends IPart>> getPartClassList() {
		return partClassList;
	}

	private URL[] getUrls(ModuleConfig mc) {
		Collection<URL> moduleUrlList = new ArrayList<URL>();
		for (String path : mc.getEntityJarPathList()) {
			try {
				URL url = new URL(mc.getRoot() + path);
				moduleUrlList.add(url);
			} catch (MalformedURLException e) {
				CatchException.take(e);
			}
		}
		return (URL[]) moduleUrlList.toArray();
	}

	private AnnotationClassLoader createLoader(URL[] urls) {
		AnnotationClassLoader ret = null;
		Thread thread = Thread.currentThread();
		ClassLoader loader = thread.getContextClassLoader();
		ret = new AnnotationClassLoader(urls, loader);
		return ret;
	}

}
